package com.xiaobaibai.security;

import com.xiaobaibai.security.filter.OptionsRequestFilter;
import com.xiaobaibai.security.handler.HttpFailureHandler;
import com.xiaobaibai.security.handler.HttpFailureHandler2;
import com.xiaobaibai.security.handler.TokenLogoutHandler;
import com.xiaobaibai.security.handler.globalErrorHandler.SimpleAccessDeniedHandler;
import com.xiaobaibai.security.handler.globalErrorHandler.SimpleAuthenticationEntryPoint;
import com.xiaobaibai.security.master_login.config.LoginConfig;
import com.xiaobaibai.security.master_login.dao.LoginUserDetailService;
import com.xiaobaibai.security.master_login.handler.MyLoginSuccessHandler;
import com.xiaobaibai.security.master_token.config.No2TokenConfig;
import com.xiaobaibai.security.master_token.handler.TokenSuccessHandler;
import com.xiaobaibai.security.master_token.provider.JwtAuthenticationProvider;
import com.xiaobaibai.security.units.TokenService;
import com.xiaobaibai.service.IUserAdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.header.Header;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private OptionsRequestFilter optionsRequestFilter;

    @Autowired
    private IUserAdminService userAdminService;

    @Autowired
    private SimpleAccessDeniedHandler simpleAccessDeniedHandler;

    @Autowired
    private SimpleAuthenticationEntryPoint simpleAuthenticationEntryPoint;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private TokenSuccessHandler tokenSuccessHandler;

    @Autowired
    private HttpFailureHandler httpFailureHandler;

    @Autowired
    private HttpFailureHandler2 httpFailureHandler2;

    @Bean
    public MyLoginSuccessHandler getLoginSuccessHandler(){
        return new MyLoginSuccessHandler(tokenService);
    }

    @Bean//密码加密类(每次的盐都会不一样,但是都会匹配)
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public JwtAuthenticationProvider jwtAuthenticationProvider(){
        return new JwtAuthenticationProvider(tokenService);
    }

    @Value("${excludeUri}")
    public String excludeUri;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
//                .antMatchers("/**").permitAll()

                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/v2/**").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()

                .antMatchers("/login","/error").permitAll()
                .antMatchers("/**").hasAnyAuthority("ADMIN")
                .anyRequest().authenticated()
                .and()

                .csrf().disable()//CRSF禁用，因为不使用session
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//禁用session
        .and()
        .formLogin().disable() //禁用form登录
        .cors()//支持跨域
        .and()
        .headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
        new Header("Access-control-Allow-Origin","*"),
        new Header("Access-Control-Expose-Headers","Authorization"))))
        .and()
        .addFilterAfter(optionsRequestFilter, CorsFilter.class)
                .apply(new LoginConfig<>()).loginSuccessHandler(getLoginSuccessHandler()).setUserDetailService(new LoginUserDetailService(userAdminService)).setPasswordEncoder(passwordEncoder()).setHttpFailureHandler(httpFailureHandler2)
                .and()
                .apply(new No2TokenConfig<>(excludeUri)).tokenSuccessHandler(tokenSuccessHandler).setJwtAuthenticationProvider(jwtAuthenticationProvider()).setFailureHandler(httpFailureHandler)
                .and()
                .logout()
                .logoutUrl("/logout")
                .addLogoutHandler(new TokenLogoutHandler())
                .logoutSuccessHandler(new TokenLogoutHandler())
        .and()
            .exceptionHandling()
                .accessDeniedHandler(simpleAccessDeniedHandler)
                .authenticationEntryPoint(simpleAuthenticationEntryPoint)
        ;
    }

    /**
     * 给重写UsernamePasswordFilter方法设置用的, 不想要了 就麻烦点吧
     */
//    @Bean
//    public AuthenticationManager authenticationManagerBean() throws Exception {
//        return super.authenticationManagerBean();
//    }


    //不明不白,这个不管了
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.authenticationProvider(daoAuthenticationProvider()).authenticationProvider(jwtAuthenticationProvider());
//    }
//
//    @Bean("daoAuthenticationProvider")
//    protected AuthenticationProvider daoAuthenticationProvider() throws Exception{
//        //这里会默认使用BCryptPasswordEncoder比对加密后的密码，注意要跟createUser时保持一致
//        DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
//        daoProvider.setUserDetailsService(userDetailsService());
//        return daoProvider;
//    }
//
//    @Override
//    protected UserDetailsService userDetailsService() {
//        return new LoginUserDetailService();
//    }

}
